package abg.core.service.jldz.impl;

import abg.core.common.properties.AbgPro;
import abg.core.common.security.AuthKit;
import abg.core.common.security.AuthUser;
import abg.core.common.util.*;
import abg.core.common.util.coll.ArrayKit;
import abg.core.common.util.password.PWD;
import abg.core.common.util.valid.Enum;
import abg.core.common.util.valid.Ids;
import abg.core.common.util.valid.NotBlank;
import abg.core.common.util.valid.base.Valid;
import abg.core.domain.db.*;
import abg.core.domain.search.*;
import abg.core.domain.sys.FileConfig;
import abg.core.domain.sys.MSG;
import abg.core.domain.sys.ServiceException;
import abg.core.mapper.*;
import abg.core.service.jldz.JldzService;
import abg.core.service.sys.SysMsgService;
import com.alibaba.fastjson2.JSON;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static abg.core.domain.db.table.AaFileTableDef.AA_FILE;
import static abg.core.domain.db.table.AaTaskTableDef.AA_TASK;
import static abg.core.domain.db.table.AaXqCjTableDef.AA_XQ_CJ;
import static abg.core.domain.db.table.AaZipTableDef.AA_ZIP;

@Slf4j
@Service
public class JldzServiceImpl implements JldzService {
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Resource
    private AbgPro abgPro;

    @Resource
    private FileConfig fileConfig;

    @Resource
    private AaXqCjMapper aaXqCjMapper;

    @Resource
    private AaTaskMapper aaTaskMapper;

    @Resource
    private AaBmMapper aaBmMapper;

    @Resource
    private AaJsMapper aaJsMapper;

    @Resource
    private AaFileMapper aaFileMapper;

    @Resource
    private AaZipMapper zipMapper;

    @Resource
    private MinioKit minioKit;

    @Resource
    private SysMsgService msgService;


    @Valid
    @Override
    public AaFile uploadAnyFile(@NotBlank MultipartFile file, String token, @Enum({"0", "1", "2"}) String taskType, String taskId, String cjNumber) throws IOException {
        AuthUser currentUser = AuthKit.mastLogin(token);

        //检查文件名和重复信息
        String originName = file.getOriginalFilename();
        if (StringKit.isBlank(originName)) throw new ServiceException(MSG.FILE_UPLOAD_ER, "文件名不能为空");

        //检查文件名和重复信息
        QueryWrapper wrapper = QueryWrapper.create().and(AA_FILE.TASK_ID.eq(taskId)).and(AA_FILE.CJ_NUMBER.eq(cjNumber)).and(AA_FILE.ORIGIN_NAME.eq(originName)).and(AA_FILE.UPLOAD_USER_ID.eq(currentUser.getUserId()));
        long l = aaFileMapper.selectCountByQuery(wrapper);
        if (l > 0) throw new ServiceException(MSG.FILE_NAME_EXISTS);

        //非任务，必须有通知编号,必须是教师
        if (taskType.equals("2")) {
            if (StringKit.isBlank(cjNumber)) throw new ServiceException(MSG.PARAM_ER);
        }
        //任务，必须有任务ID
        else {
            if (StringKit.isBlank(taskId)) throw new ServiceException(MSG.PARAM_ER);
        }

        InputStream inputStreamMd5;
        InputStream inputStreamUpload;
        try {
            inputStreamMd5 = file.getInputStream();
            inputStreamUpload = file.getInputStream();
        } catch (IOException e) {
            throw new ServiceException(MSG.FILE_UPLOAD_ER, e.getMessage());
        }

        //上传至第三方云服务或服务器
        String fileType = originName.substring(originName.lastIndexOf(".") + 1);
        String id = IdKit.getId();
        String reName = id + "." + fileType;

        //硬存
        String md5 = FileKit.getMD5(inputStreamMd5);
        String URI;
        if (abgPro.getEnv().equals("dev")) {
            URI = minioKit.uploadGetURI(inputStreamUpload, originName, file.getContentType());
        } else {
            URI = minioKit.uploadGetURIIntranet(inputStreamUpload, originName, file.getContentType());
        }
        inputStreamUpload.close();

        //保存数据信息至数据库
        AaFile aaFile = new AaFile();
        aaFile.setId(id);
        aaFile.setName(originName);
//        aaFile.setName(reName);
        aaFile.setUri(URI);
        aaFile.setOriginName(originName);
        aaFile.setFileType(fileType);
        aaFile.setBType("0");
        aaFile.setBucket(fileConfig.minioBucketName());
        aaFile.setUploadUserId(currentUser.getUserId());
        aaFile.setSize(file.getSize());
        aaFile.setMd5(md5);
        aaFile.setDomain(fileConfig.minioUrlPrefix());
        //任务类型
        aaFile.setTaskId(taskId);
        aaFile.setTaskType(taskType);

        //教师上传资料
        if (taskType.equals("2")) {
            AaXqCj aaXqCj = aaXqCjMapper.selectColumnByKey("number", cjNumber, " * ");
            aaFile.setCjNumber(aaXqCj.getNumber());
            aaFile.setKcNumber(aaXqCj.getKcNumber());
            aaFile.setJsNumber(aaXqCj.getJsNumber());
            aaFile.setBmCode(aaXqCj.getBmCode());
        } else {
            //教师任务
            if (taskType.equals("0")) {
                aaFile.setJsNumber(getJsNumber());
            }
            //部门任务
            if (taskType.equals("1")) {
                aaFile.setBmCode(getBmCode());
            }
        }

        //插入数据
        aaFileMapper.insertSelective(aaFile);
        return aaFile;
    }


    //生成教师课程资料压缩包
    @Override
    public boolean createJsZip(String bmCode, String createUserType, String zipType, String zipName, ArrayList<String> cjNumberList) {
        String userId = AuthKit.mastLogin().getUserId();
        String fileName = zipName + ".zip";

        //记录文件开始生成的通知
        saveMsg("文件开始生成", fileName, "压缩包已经开始生成，生成完毕后，会收到系统通知。请注意查看系统通知。", userId);

        ThreadKit.getPool().execute(() -> {
            AaZip aaZip = new AaZip();
            String zipId = IdKit.getId();
            aaZip.setId(zipId);
            aaZip.setZipName(fileName);
            aaZip.setCreateUserType(createUserType);
            aaZip.setZipType(zipType);
            aaZip.setBmCode(bmCode);
            aaZip.setUserId(userId);
            zipMapper.insertSelective(aaZip);

            try {
                log.error(" aaZip {}", JSON.toJSONString(aaZip));

                //查询教师资料
                QueryWrapper wrapper = QueryWrapper.create().and(AA_XQ_CJ.BM_CODE.in(bmCode)).and(AA_XQ_CJ.NUMBER.in(cjNumberList));
                List<AaXqCj> aaXqCjs = aaXqCjMapper.selectListByQuery(wrapper);
                if (aaXqCjs.size() == 0) throw new ServiceException("查询数据失败");

                //读取所有文件信息和流信息
                ArrayList<String> zipNameList = new ArrayList<>();
                ArrayList<PipedInputStream> pisList = new ArrayList<>();
                for (AaXqCj aaXqCj : aaXqCjs) {
                    QueryWrapper wrapperFile = QueryWrapper.create().and(AA_FILE.BM_CODE.eq(bmCode)).and(AA_FILE.TASK_TYPE.eq("2"))//非任务
                            .and(AA_FILE.JS_NUMBER.eq(aaXqCj.getJsNumber())).and(AA_FILE.KC_NUMBER.eq(aaXqCj.getKcNumber()));
                    List<AaFile> aaFiles = aaFileMapper.selectListByQuery(wrapperFile);

                    //压缩包名
                    String cjZipName = aaXqCj.getBmName() + "-" + aaXqCj.getName() + "-" + aaXqCj.getKcName() + "-" + aaXqCj.getJsName() + ".zip";
                    zipNameList.add(cjZipName);

                    //minio存放地址
                    List<String> minioPathList = aaFiles.stream().map(AaFile::getName).toList();

                    //包内文件名
                    List<String> fileOriginNameList = aaFiles.stream().map(AaFile::getOriginName).toList();

                    //包内文件流
                    ArrayList<FilterInputStream> fileStreamList = new ArrayList<>();
                    for (String minioFilePath : minioPathList) {
                        FilterInputStream inputStream;
                        if (abgPro.getEnv().equals("dev")) {
                            inputStream = minioKit.getFileStream(minioFilePath);
                        } else {
                            inputStream = minioKit.getFileStreamIntranet(minioFilePath);
                        }
                        if (inputStream == null) continue;
                        fileStreamList.add(inputStream);
                    }
                    // 创建 PipedInputStream 和 PipedOutputStream 对象
                    PipedOutputStream pos = new PipedOutputStream();
                    PipedInputStream pis = new PipedInputStream(pos);
                    pisList.add(pis);
                    ZipKit.zipToPos(pos, fileOriginNameList, fileStreamList, 1024 * 100);
                }
                log.error("zipNameList {}", JSON.toJSONString(zipNameList));

                //生成本地文件，上传，删除，更新数据信息
                createAndUpdateZipInfo(zipNameList, pisList, aaZip.getZipName(), zipId);

                // 通知文件生成完毕
                saveMsg("文件生成完毕", fileName, "压缩包已经生成完毕。", userId);

            } catch (Exception e) {
                createZipError(userId, fileName, zipId, e);
            }
        });

        return true;
    }


    //生成任务压缩包
    @Valid
    @Override
    public boolean createTaskZip(String zipType, String createUserType, @NotBlank String zipName, @Enum({"0", "1"}) String taskType, ArrayList<String> taskIdList) {
        String userId = AuthKit.mastLogin().getUserId();
        String fileName = zipName + ".zip";
        saveMsg("文件开始生成", fileName, "压缩包已经开始生成，生成完毕后，会收到系统通知。请注意查看系统通知。", userId);

        ThreadKit.getPool().execute(() -> {
            AaZip aaZip = new AaZip();
            String zipId = IdKit.getId();
            aaZip.setId(zipId);
            aaZip.setZipName(fileName);
            aaZip.setCreateUserType(createUserType);
            aaZip.setZipType(zipType);
            aaZip.setTaskType(taskType);
            aaZip.setBmCode(null);
            aaZip.setUserId(userId);
            zipMapper.insertSelective(aaZip);

            try {
                log.error(" aaZip {}", JSON.toJSONString(aaZip));
                QueryWrapper wp = QueryWrapper.create().and(AA_TASK.ID.in(taskIdList));
                List<AaTask> taskList = aaTaskMapper.selectListByQuery(wp);
                if (taskList.size() == 0) throw new ServiceException("查询数据失败");


                //读取所有文件信息和流信息
                ArrayList<String> zipNameList = new ArrayList<>();
                ArrayList<PipedInputStream> pisList = new ArrayList<>();
                for (AaTask task : taskList) {
                    QueryWrapper wrapperFile = QueryWrapper.create().and(AA_FILE.TASK_ID.eq(task.getId()));
                    List<AaFile> aaFiles = aaFileMapper.selectListByQuery(wrapperFile);

                    //压缩包名
                    String cjZipName = task.getName() + ".zip";
                    zipNameList.add(cjZipName);
                    //minio存放地址
                    List<String> minioPathList = aaFiles.stream().map(AaFile::getName).toList();

                    //包内文件名
                    List<String> fileOriginNameList = aaFiles.stream().map(AaFile::getOriginName).toList();
                    //包内文件流
                    ArrayList<FilterInputStream> fileStreamList = new ArrayList<>();
                    for (String minioFilePath : minioPathList) {
                        FilterInputStream inputStream = null;
                        try {
                            if (abgPro.getEnv().equals("dev")) {
                                inputStream = minioKit.getFileStream(minioFilePath);
                            } else {
                                inputStream = minioKit.getFileStreamIntranet(minioFilePath);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        if (inputStream == null) continue;
                        fileStreamList.add(inputStream);
                    }
                    // 创建 PipedInputStream 和 PipedOutputStream 对象
                    PipedOutputStream pos = new PipedOutputStream();
                    PipedInputStream pis = new PipedInputStream(pos);
                    pisList.add(pis);
                    ZipKit.zipToPos(pos, fileOriginNameList, fileStreamList, 1024 * 100);
                }

                log.error("zipNameList {}", JSON.toJSONString(zipNameList));

                //更新文件大小
                createAndUpdateZipInfo(zipNameList, pisList, aaZip.getZipName(), zipId);
                // 通知文件生成完毕
                saveMsg("文件生成完毕", fileName, "压缩包已经生成完毕。", userId);
            } catch (Exception e) {
                createZipError(userId, fileName, zipId, e);
            }
        });
        return true;
    }

    //生成文件，上传，更新数据信息
    private void createAndUpdateZipInfo(ArrayList<String> zipNameList, ArrayList<PipedInputStream> pisList, String fileName, String zipId) throws Exception {
        String uriPath = "/zip/" + zipId + "/" + fileName;
        String zipPath = "static" + uriPath;
        File file = new File(zipPath);
        if (!file.exists()) {
            // 确保父目录存在，如果不存在则创建目录
            File parentDir = file.getParentFile();
            if (!parentDir.exists()) {
                parentDir.mkdirs();
            }
        }
        log.error("开始写文件....");
        FileOutputStream fileOutputStream = new FileOutputStream(zipPath);
        ZipKit.downloadLocal(fileOutputStream, zipNameList, pisList, 1024 * 100);
        fileOutputStream.close();
        log.error("文件已写完....");

        //计算MD5
        log.error("开始上传....");
        FileInputStream inputStreamMd5 = new FileInputStream(zipPath);
        String md5 = FileKit.getMD5(inputStreamMd5);
        inputStreamMd5.close();

        //上传
        File file1 = new File(zipPath);
        long allSize = file1.length();
        //        FileInputStream fileInputStream = new FileInputStream(file1);
        //        String URI;
        //        if (ablPro.getEnv().equals("dev")) {
        //            URI = minioKit.uploadGetURI(fileInputStream, fileName, "application/zip");
        //        } else {
        //            URI = minioKit.uploadGetURIIntranet(fileInputStream, fileName, "application/zip");
        //        }
        //        fileInputStream.close();

        //删除本地临时文件
        //        File file = new File(fileName);
        //        boolean delete = file.delete();
        //        log.error("文件已删除 " + delete + "  " + file.getName() + "  " + file.getPath());

        //更新数据状态
        AaZip updateZip = new AaZip();
        updateZip.setId(zipId);
        updateZip.setSize(allSize + "");
        updateZip.setCreateStatus("1");
        updateZip.setUri(uriPath);
        updateZip.setFileType("application/zip");
        updateZip.setBucket(null);
        updateZip.setMd5(md5);
        updateZip.setDomain(abgPro.getZipDoMain());

        log.error(" 文件上传完成，返回结果 " + JSON.toJSONString(updateZip));

        zipMapper.update(updateZip);
    }

    private void createZipError(String userId, String fileName, String zipId, Exception e) {
        AaZip updateZip = new AaZip();
        updateZip.setId(zipId);
        updateZip.setCreateStatus("2");
        updateZip.setErrorMsg(StringKit.getExceptionMsg(e));
        zipMapper.update(updateZip);
        e.printStackTrace();

        saveMsg("文件生成失败", fileName, "压缩包生成失败，请您重新操作。", userId);
    }

    //保存文件生成信息
    private void saveMsg(String title, String fileName, String x, String userId) {
        SysMsg sysMsg = new SysMsg();
        sysMsg.setTitle(title);
        sysMsg.setContent("【" + fileName + "】 " + x);
        sysMsg.setSendToUserIds(ArrayKit.asList(userId));
        msgService.insert(sysMsg);
    }

    //查压缩包文件分页数据
    @Override
    public Page pageZip(ZipPsh pageSearch) {
        QueryWrapper wrapper = QueryWrapper.create().from(AaZip.class)//
                .and(AA_ZIP.ZIP_NAME.eq(pageSearch.getZipName()))//
                .and(AA_ZIP.BM_CODE.eq(pageSearch.getBmCode()))//
                .and(AA_ZIP.TASK_TYPE.eq(pageSearch.getTaskType()))//任务类型；0教师任务；1部门任务；
                .and(AA_ZIP.ZIP_TYPE.eq(pageSearch.getZipType()))//教师资料0；教务任务1
                .and(AA_ZIP.CREATE_USER_TYPE.eq(pageSearch.getCreateUserType()))//生成人身份；部门0；教务处1；
                .and(AA_ZIP.CT.ge(pageSearch.getStartTime()))//
                .and(AA_ZIP.CT.le(pageSearch.getEndTime()))//
                .orderBy(AA_ZIP.CT.desc());
        Page paginate = zipMapper.paginate(pageSearch, wrapper);

        return paginate;
    }

    @Valid
    @Override
    public void jwDeleteZipFile(@Ids String ids) {
        ArrayList<String> idList = StringKit.split(ids);
        QueryWrapper wrapper = QueryWrapper.create().and(AA_ZIP.CREATE_USER_TYPE.eq("1")).and(AA_ZIP.ID.in(idList));
        zipMapper.deleteByQuery(wrapper);
    }

    @Valid
    @Override
    public void bmDeleteZipFile(@Ids String ids) {
        ArrayList<String> idList = StringKit.split(ids);
        QueryWrapper wrapper = QueryWrapper.create().and(AA_ZIP.BM_CODE.eq(getBmCode())).and(AA_ZIP.CREATE_USER_TYPE.eq("0")).and(AA_ZIP.ID.in(idList));
        zipMapper.deleteByQuery(wrapper);
    }

    @Override
    public Object ddUpload() {
        return null;
    }

    //课程任务
    @Override
    public Page<AaXqCj> teacherCourse(TCoursePsh pageSearch) {
        QueryWrapper wrapper = QueryWrapper.create().from(AA_XQ_CJ).where(AA_XQ_CJ.KC_NUMBER.like(pageSearch.getKcNumber()))//
                .and(AA_XQ_CJ.KC_NAME.like(pageSearch.getKcName()))//
                .and(AA_XQ_CJ.BM_NAME.like(pageSearch.getBmName()))//
                .and(AA_XQ_CJ.BM_CODE.like(pageSearch.getBmCode()))//
                .and(AA_XQ_CJ.JS_NAME.like(pageSearch.getCjsName()))//
                .and(AA_XQ_CJ.JS_NUMBER.like(pageSearch.getCjsNumber()))//
                .and(AA_XQ_CJ.NAME.like(pageSearch.getName()));
        Page paginate = aaXqCjMapper.paginate(pageSearch, wrapper);
        return paginate;
    }

    //课程任务
    @Override
    public Page<AaFile> teacherCourseFile(TCourseFilePsh pageSearch) {
        if (StringKit.isBlank(pageSearch.getCjNumber())) throw new ServiceException(MSG.PARAM_ER);

        QueryWrapper wrapper = QueryWrapper.create().from(AaFile.class).where(AA_FILE.NAME.like(pageSearch.getName()))//
                .and(AA_FILE.ORIGIN_NAME.like(pageSearch.getOriginName()))//
                .and(AA_FILE.CJ_NUMBER.eq(pageSearch.getCjNumber()))//
                .and(AA_FILE.KC_NUMBER.eq(pageSearch.getKcNumber()))//
                .and(AA_FILE.JS_NUMBER.eq(pageSearch.getJsNumber()))//
                .and(AA_FILE.CT.ge(pageSearch.getStartTime()))//
                .and(AA_FILE.CT.le(pageSearch.getEndTime()))//
                ;
        Page paginate = aaFileMapper.paginate(pageSearch, wrapper);
        return paginate;
    }

    @Override
    public Page taskFile(TCourseFilePsh pageSearch) {
        if (StringKit.isBlank(pageSearch.getTaskId())) throw new ServiceException(MSG.PARAM_ER);

        QueryWrapper wrapper = QueryWrapper.create().from(AaFile.class).where(AA_FILE.NAME.like(pageSearch.getName()))//
                .and(AA_FILE.ORIGIN_NAME.like(pageSearch.getOriginName()))//
                .and(AA_FILE.JS_NUMBER.eq(pageSearch.getJsNumber()))//
                .and(AA_FILE.BM_CODE.eq(pageSearch.getBmCode()))//
                .and(AA_FILE.TASK_ID.eq(pageSearch.getTaskId()))//
                .and(AA_FILE.CT.ge(pageSearch.getStartTime()))//
                .and(AA_FILE.CT.le(pageSearch.getEndTime()))//
                ;

        Page paginate = aaFileMapper.paginate(pageSearch, wrapper);
        return paginate;
    }

    //教务处任务
    @Override
    public Page<AaTask> teacherTask(TTaskPsh pageSearch) {
        QueryWrapper wrapper = QueryWrapper.create().from(AA_TASK).and(AA_TASK.NAME.like(pageSearch.getName()))//
                .and(AA_TASK.REMARK.ge(pageSearch.getRemark()))//
                .and(AA_TASK.START_TIME.ge(pageSearch.getStartTime()))//
                .and(AA_TASK.END_TIME.le(pageSearch.getEndTime()))//
                .where(AA_TASK.IS_OPEN.eq("0"))//
                .and(AA_TASK.TYPE.eq("0"));//

        Page paginate = aaTaskMapper.paginate(pageSearch, wrapper);
        return paginate;
    }

    @Override
    public boolean deleteFile(String ids) {
        ArrayList<String> split = StringKit.split(ids);

        aaFileMapper.deleteBatchByIds(split);

        return true;
    }

    //教务处任务分页查询
    @Override
    public Page<AaTask> jwPageTask(JwTaskPsh pageSearch) {
        QueryWrapper wrapper = QueryWrapper.create().from(AA_TASK).and(AA_TASK.NAME.like(pageSearch.getName()))//
                .and(AA_TASK.ID.like(pageSearch.getId()))//
                .and(AA_TASK.REMARK.like(pageSearch.getRemark()))//
                .and(AA_TASK.IS_OPEN.eq(pageSearch.getIsOpen()))//
                .and(AA_TASK.TYPE.eq(pageSearch.getType())).and(AA_TASK.START_TIME.ge(pageSearch.getStartTime()))//
                .and(AA_TASK.END_TIME.le(pageSearch.getEndTime()))//
                ;//

        Page paginate = aaTaskMapper.paginate(pageSearch, wrapper);

        return paginate;
    }

    //教务处添加任务
    @Override
    public boolean jwAddTask(AaTask param) {
        param.setId(IdKit.getId());
        param.setCt(LocalDateTime.now());
        aaTaskMapper.insertSelective(param);
        return true;
    }

    @Override
    public boolean jwUpdateTask(AaTask param) {
        param.setUt(LocalDateTime.now());
        aaTaskMapper.update(param);
        return true;
    }

    //教务处修改任务状态
    @Valid
    @Override
    public boolean updateTaskStatus(@Ids String ids, @Enum({"0", "1"}) String isOpen) {
        ArrayList<String> idList = StringKit.split(ids);
        AaTask aaTask = new AaTask();
        aaTask.setIsOpen(isOpen);
        aaTaskMapper.updateByQuery(aaTask, QueryWrapper.create().and(AA_TASK.ID.in(idList)));
        return true;
    }

    //教务处删除任务
    @Valid
    @Override
    public boolean jwDelTask(@Ids String ids) {
        ArrayList<String> idList = StringKit.split(ids);
        aaTaskMapper.deleteBatchByIds(idList);
        return true;
    }

    @Override
    public void downloadZip(String paths, String zipName) throws Exception {
        int readSize = 1024 * 200;
        //
        //
        ArrayList<String> pathList1 = StringKit.split("1176563504614735872.keystore,1176570926494384128.txt");
        ArrayList<String> fileNames1 = new ArrayList<>();
        ArrayList<FilterInputStream> streamList1 = new ArrayList<>();
        for (String minioFilePath : pathList1) {
            FilterInputStream inputStream;
            if (abgPro.getEnv().equals("dev")) {
                inputStream = minioKit.getFileStream(minioFilePath);
            } else {
                inputStream = minioKit.getFileStreamIntranet(minioFilePath);
            }
            if (inputStream == null) continue;
            streamList1.add(inputStream);
            fileNames1.add(minioFilePath);
        }
        //
        //
        ArrayList<String> pathList2 = StringKit.split("1176901577366044672.txt,1176901589047181312.txt");
        ArrayList<String> fileNames2 = new ArrayList<>();
        ArrayList<FilterInputStream> streamList2 = new ArrayList<>();
        for (String minioFilePath : pathList2) {
            FilterInputStream inputStream;
            if (abgPro.getEnv().equals("dev")) {
                inputStream = minioKit.getFileStream(minioFilePath);
            } else {
                inputStream = minioKit.getFileStreamIntranet(minioFilePath);
            }
            if (inputStream == null) continue;
            streamList2.add(inputStream);
            fileNames2.add(minioFilePath);
        }

        // 创建 PipedInputStream 和 PipedOutputStream 对象
        PipedOutputStream pos1 = new PipedOutputStream();
        PipedInputStream pis1 = new PipedInputStream(pos1);

        PipedOutputStream pos2 = new PipedOutputStream();
        PipedInputStream pis2 = new PipedInputStream(pos2);

        ZipKit.zipToPos(pos1, fileNames1, streamList1, readSize);

        ZipKit.zipToPos(pos2, fileNames2, streamList2, readSize);

        //
        String zipName1 = "123.zip";
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.reset();
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(zipName1, StandardCharsets.UTF_8));
        response.setCharacterEncoding("utf-8");

//        ZipKit.download(response, "压缩包001.zip", pis1, readSize);
        ZipKit.download(response, ArrayKit.asList("压缩包001.zip", "压缩包002.zip"), ArrayKit.asList(pis1, pis2), readSize);


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void initUserAccount() {
        //所有教师
        List<AaJs> aaJsAll = aaJsMapper.selectAll();
        for (AaJs js : aaJsAll) {
            SysUser columnByKey = sysUserMapper.selectColumnByKey("account", js.getNumber(), "id");
            if (columnByKey == null) {
                //插入教师用户
                SysUser sysUser = new SysUser();
                sysUser.setId(IdKit.getId());
                sysUser.setAccount(js.getNumber());
                sysUser.setJsNumber(js.getNumber());
                sysUser.setBmCode(js.getBmCode());
                sysUser.setNickName(js.getName());
                sysUser.setPassword(PWD.createPwdByPlain("123456"));
                sysUserMapper.insertSelective(sysUser);

                //插入教师角色
                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setUserId(sysUser.getId());
                sysUserRole.setRoleId("40");
                sysUserRoleMapper.insertSelective(sysUserRole);
            }
        }

        //所有部门
        List<AaBm> aaBmAll = aaBmMapper.selectAll();
        for (AaBm bm : aaBmAll) {
            SysUser columnByKey = sysUserMapper.selectColumnByKey("account", bm.getCode(), "id");
            if (columnByKey == null) {
                //插入部门用户
                SysUser sysUser = new SysUser();
                sysUser.setId(IdKit.getId());
                sysUser.setAccount(bm.getCode());
                sysUser.setNickName(bm.getName());
                sysUser.setBmCode(bm.getCode());
                sysUser.setPassword(PWD.createPwdByPlain("123456"));
                sysUserMapper.insertSelective(sysUser);

                //插入部门角色
                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setUserId(sysUser.getId());
                sysUserRole.setRoleId("50");
                sysUserRoleMapper.insert(sysUserRole);
            }
        }
    }

    //部门打包下载教师资料
    @Valid
    @Override
    public void jwDownloadJsZip(@Ids String cjNumbers, String type, QueryWrapper wrapper) throws Exception {

        List<AaXqCj> aaXqCjs = aaXqCjMapper.selectListByQuery(wrapper);
        if (aaXqCjs.size() == 0) throw new ServiceException("查询数据失败");

        if ("1".equals(type)) {
            downloadJsOneZip(getBmCode(), aaXqCjs.get(0));
        }

        if ("2".equals(type)) {
            downloadJsZipList(getBmCode(), aaXqCjs);
        }
    }

    //教务打包下载任务，或者，教师资料
    @Override
    public void jwDownloadZip(String taskIds, String cjNumbers, String type, QueryWrapper wrapper) throws Exception {
        //教师资料
        if (StringKit.isNotBlank(cjNumbers)) {
            jwDownloadJsZip(cjNumbers, type, wrapper);
        }

        //任务资料
        if (StringKit.isNotBlank(taskIds)) {
            //所有任务
            ArrayList<String> taskIdListList = StringKit.split(taskIds);
            QueryWrapper wp = QueryWrapper.create().and(AA_TASK.ID.in(taskIdListList));
            List<AaTask> taskList = aaTaskMapper.selectListByQuery(wp);
            if (taskList.size() == 0) throw new ServiceException("查询数据失败");
            if ("1".equals(type)) {
                downloadTaskOneZip(taskList.get(0));
            }
            if ("2".equals(type)) {
                downloadTaskZipList(taskList);
            }
        }

    }


    //当前登录用户的部门code
    @Override
    public String getBmCode() {
        AuthUser authUser = AuthKit.mastLogin();
        SysUser sysUser = sysUserMapper.selectOneById(authUser.getUserId());
        String bmCode = sysUser.getBmCode();
        if (StringKit.isBlank(bmCode)) return "0";
        return bmCode;
    }

    //当前登录用户的教师编号
    @Override
    public String getJsNumber() {
        AuthUser authUser = AuthKit.mastLogin();
        SysUser sysUser = sysUserMapper.selectOneById(authUser.getUserId());
        String jsNumber = sysUser.getJsNumber();
        if (StringKit.isBlank(jsNumber)) return "0";
        return jsNumber;
    }

    //下载一门课程
    private void downloadTaskOneZip(AaTask aaTask) throws Exception {
        List<String> fileNameList = new ArrayList<>();
        List<InputStream> fileInputList = new ArrayList<>();

        //打包
        QueryWrapper wrapperFile = QueryWrapper.create().and(AA_FILE.TASK_ID.eq(aaTask.getId()));
        List<AaFile> aaFiles = aaFileMapper.selectListByQuery(wrapperFile);

        if (aaFiles.size() > 0) {
            fileNameList = aaFiles.stream().map(AaFile::getOriginName).toList();
            List<String> filePathList = aaFiles.stream().map(AaFile::getName).toList();
            for (String minioFilePath : filePathList) {
                FilterInputStream inputStream = null;
                try {
                    if (abgPro.getEnv().equals("dev")) {
                        inputStream = minioKit.getFileStream(minioFilePath);
                    } else {
                        inputStream = minioKit.getFileStreamIntranet(minioFilePath);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (inputStream == null) continue;
                fileInputList.add(inputStream);
            }
        }

        //
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.reset();
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("压缩包.zip", StandardCharsets.UTF_8));
        response.setCharacterEncoding("utf-8");
        ZipKit.download(response, fileNameList, fileInputList, 1024 * 100);
    }

    private void downloadTaskZipList(List<AaTask> tasks) throws Exception {
        ArrayList<String> zipNameList = new ArrayList<>();
        ArrayList<PipedInputStream> pisList = new ArrayList<>();

        //打包
        for (AaTask task : tasks) {
            QueryWrapper wrapperFile = QueryWrapper.create().and(AA_FILE.TASK_ID.eq(task.getId()));
            List<AaFile> aaFiles = aaFileMapper.selectListByQuery(wrapperFile);

            //压缩包名
            String cjZipName = task.getName() + ".zip";
            zipNameList.add(cjZipName);
            //minio存放地址
            List<String> minioPathList = aaFiles.stream().map(AaFile::getName).toList();

            //包内文件名
            List<String> fileOriginNameList = aaFiles.stream().map(AaFile::getOriginName).toList();
            //包内文件流
            ArrayList<FilterInputStream> fileStreamList = new ArrayList<>();
            for (String minioFilePath : minioPathList) {
                FilterInputStream inputStream = null;
                try {
                    if (abgPro.getEnv().equals("dev")) {
                        inputStream = minioKit.getFileStream(minioFilePath);
                    } else {
                        inputStream = minioKit.getFileStreamIntranet(minioFilePath);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (inputStream == null) continue;
                fileStreamList.add(inputStream);
            }
            // 创建 PipedInputStream 和 PipedOutputStream 对象
            PipedOutputStream pos = new PipedOutputStream();
            PipedInputStream pis = new PipedInputStream(pos);
            pisList.add(pis);
            ZipKit.zipToPos(pos, fileOriginNameList, fileStreamList, 1024 * 100);
        }

        //
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.reset();
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("压缩包.zip", StandardCharsets.UTF_8));
        response.setCharacterEncoding("utf-8");
        //        ZipKit.download(response, "压缩包001.zip", pis1, readSize);
        ZipKit.download(response, zipNameList, pisList, 1024 * 100);
    }

    //下载一门课程
    private void downloadJsOneZip(String bmCode, AaXqCj aaXqCj) throws Exception {
        List<String> fileNameList = new ArrayList<>();
        List<InputStream> fileInputList = new ArrayList<>();

        //打包
        QueryWrapper wrapperFile = QueryWrapper.create().and(AA_FILE.BM_CODE.eq(bmCode)).and(AA_FILE.TASK_TYPE.eq("2"))//非任务
                .and(AA_FILE.JS_NUMBER.eq(aaXqCj.getJsNumber())).and(AA_FILE.KC_NUMBER.eq(aaXqCj.getKcNumber()));
        List<AaFile> aaFiles = aaFileMapper.selectListByQuery(wrapperFile);

        if (aaFiles.size() > 0) {
            fileNameList = aaFiles.stream().map(AaFile::getOriginName).toList();
            List<String> filePathList = aaFiles.stream().map(AaFile::getName).toList();
            for (String minioFilePath : filePathList) {
                FilterInputStream inputStream = null;
                try {
                    if (abgPro.getEnv().equals("dev")) {
                        inputStream = minioKit.getFileStream(minioFilePath);
                    } else {
                        inputStream = minioKit.getFileStreamIntranet(minioFilePath);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (inputStream == null) continue;
                fileInputList.add(inputStream);
            }
        }

        //
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.reset();
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("压缩包.zip", StandardCharsets.UTF_8));
        response.setCharacterEncoding("utf-8");
        ZipKit.download(response, fileNameList, fileInputList, 1024 * 100);
    }

    private void downloadJsZipList(String bmCode, List<AaXqCj> aaXqCjs) throws Exception {
        ArrayList<String> zipNameList = new ArrayList<>();
        ArrayList<PipedInputStream> pisList = new ArrayList<>();

        //打包
        for (AaXqCj aaXqCj : aaXqCjs) {
            QueryWrapper wrapperFile = QueryWrapper.create().and(AA_FILE.BM_CODE.eq(bmCode)).and(AA_FILE.TASK_TYPE.eq("2"))//非任务
                    .and(AA_FILE.JS_NUMBER.eq(aaXqCj.getJsNumber())).and(AA_FILE.KC_NUMBER.eq(aaXqCj.getKcNumber()));
            List<AaFile> aaFiles = aaFileMapper.selectListByQuery(wrapperFile);

            //压缩包名
            String cjZipName = aaXqCj.getBmName() + "-" + aaXqCj.getName() + "-" + aaXqCj.getKcName() + "-" + aaXqCj.getJsName() + ".zip";
            zipNameList.add(cjZipName);
            //minio存放地址
            List<String> minioPathList = aaFiles.stream().map(AaFile::getName).toList();

            //包内文件名
            List<String> fileOriginNameList = aaFiles.stream().map(AaFile::getOriginName).toList();
            //包内文件流
            ArrayList<FilterInputStream> fileStreamList = new ArrayList<>();
            for (String minioFilePath : minioPathList) {
                FilterInputStream inputStream = null;
                try {
                    if (abgPro.getEnv().equals("dev")) {
                        inputStream = minioKit.getFileStream(minioFilePath);
                    } else {
                        inputStream = minioKit.getFileStreamIntranet(minioFilePath);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (inputStream == null) continue;
                fileStreamList.add(inputStream);
            }
            // 创建 PipedInputStream 和 PipedOutputStream 对象
            PipedOutputStream pos = new PipedOutputStream();
            PipedInputStream pis = new PipedInputStream(pos);
            pisList.add(pis);
            ZipKit.zipToPos(pos, fileOriginNameList, fileStreamList, 1024 * 100);
        }

        //
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        response.reset();
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("压缩包.zip", StandardCharsets.UTF_8));
        response.setCharacterEncoding("utf-8");
        //        ZipKit.download(response, "压缩包001.zip", pis1, readSize);
        ZipKit.download(response, zipNameList, pisList, 1024 * 100);
    }

}